package com.yz.jdd.voice;

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;

import com.com.yunzong.rainbowbridge.CallBackService;
import com.com.yunzong.rainbowbridge.network.Request_CallBack;
import com.unisound.client.SpeechConstants;
import com.unisound.client.SpeechSynthesizer;
import com.unisound.client.SpeechSynthesizerListener;
import com.yz.jdd.base.MyApplication;
import com.yz.jdd.base.utils.BaseConfigs;
import com.yz.jdd.base.utils.Constants;
import com.yz.jdd.base.utils.LogUtils;
import com.yz.jdd.base.utils.PreferencesUtils;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


/**
 * 离线语音
 *
 * @author ing
 * @date 2018/3/27
 */
public class SpeechUtilOffline {
    public static final String appKey = "123";
    public static final String secret = "456";
    private static SpeechUtilOffline instance;
    private SpeechSynthesizer mTTSPlayer;
    private boolean isSpeaking = false;
    private List<OrderVoice> speechList = new ArrayList<>();
    List<OrderVoice> removeSpeechList = new ArrayList<>();


    private List<Request_CallBack> speechCallbackList = new ArrayList<>();
    private boolean released = false;
    protected OfflineResource offlineResource;


    AudioManager am;
    int volume;
    Context mContext;

    private SpeechUtilOffline(Context context) {
        mContext = context;
        init(context);
        released = false;
    }

    public static SpeechUtilOffline getInstance(Context context) {
        if (instance == null) {
            instance = new SpeechUtilOffline(context);
        }
        return instance;
    }

    /**
     * 初始化引擎
     *
     * @author JPH
     * @date 2015-4-14 下午7:32:58
     */
    private void init(final Context context) {
        try {
            offlineResource = new OfflineResource(context);
        } catch (IOException e) {
            LogUtils.e("=== TTS init exception : "+ e.getMessage());
            // Log.e("ing", "offlineResouce failed , error msg : " + e.getMessage());
            e.printStackTrace();
        }
        // 初始化语音合成对象
        mTTSPlayer = new SpeechSynthesizer(context, appKey, secret);
        // 设置本地合成
        mTTSPlayer.setOption(SpeechConstants.TTS_SERVICE_MODE, SpeechConstants.TTS_SERVICE_MODE_LOCAL);
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_PITCH, 50);//音调
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_SPEED, 52);//语速
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_VOLUME, 99);//音量
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_STREAM_TYPE, AudioManager.STREAM_MUSIC);
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_FRONTEND_MODEL_PATH, offlineResource.getModelFilename());
        // 设置后端模型
        mTTSPlayer.setOption(SpeechConstants.TTS_KEY_BACKEND_MODEL_PATH, offlineResource.getBackFilename());
        // 设置回调监听
        mTTSPlayer.setTTSListener(new SpeechSynthesizerListener() {

            @Override
            public void onEvent(int type) {
                switch (type) {
                    case SpeechConstants.TTS_EVENT_INIT:
                        // 初始化成功回调
                        LogUtils.i("=== 初始化成功回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_SYNTHESIZER_START:
                        // 开始合成回调
                        LogUtils.i("=== 开始合成回调  ");
                        isSpeaking = true;

                        //获取当前声音大小
                        am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
                        volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);

                        /*修改第二个参数为一个固定的值，就是设置成功。下面的方法：获取音乐类型的音频流的最大值*/
                        am.setStreamVolume(AudioManager.STREAM_MUSIC,
                                am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), AudioManager.FX_KEY_CLICK);
                        break;
                    case SpeechConstants.TTS_EVENT_SYNTHESIZER_END:
                        // 合成结束回调
                        LogUtils.i("=== 合成结束回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_BUFFER_BEGIN:
                        // 开始缓存回调
                        LogUtils.i("=== 开始缓存回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_BUFFER_READY:
                        // 缓存完毕回调
                        LogUtils.i("=== 缓存完毕回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_PLAYING_START:
                        // 开始播放回调
                        LogUtils.i("=== 开始播放回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_PLAYING_END:
                        // 播放完成回调 2
                        LogUtils.i("=== 播放完成回调  ");
                        /*修改第二个参数为一个固定的值，就是设置成功。下面的方法：获取音乐类型的音频流的最大值*/
                        am.setStreamVolume(AudioManager.STREAM_MUSIC,
                                volume, AudioManager.FX_KEY_CLICK);
                        try {
                            //TODO 回调 这是干嘛用的？？
                            if (speechCallbackList != null && speechCallbackList.size() > 0) {
                                LogUtils.e("=== speechError------>onCompleted---" + speechCallbackList.size());
                                for (Request_CallBack request_callBack : speechCallbackList) {
                                    request_callBack.setBroadcastResult(BaseConfigs.BROADCASTRESULT.SUCCESS);
                                    long endPlayTime = System.currentTimeMillis();
                                    request_callBack.setBroadcastTime((endPlayTime - request_callBack.getBeginPlayTimeLong()) + "");
                                    request_callBack.setEndPlayTime(endPlayTime + "");

                                }
                                Intent intent = new Intent(MyApplication.application, CallBackService.class);
                                intent.putExtra("speechCallbackList", (Serializable) speechCallbackList);
                                MyApplication.application.startService(intent);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
//                            LogBackUtil.e(e.toString());
                        }

                        isSpeaking = false;
                        if (speechList.size() > 0) {
                            updateSpeech();
                        }

                        break;
                    case SpeechConstants.TTS_EVENT_PAUSE:
                        // 暂停回调
                        LogUtils.i("=== 暂停回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_RESUME:
                        // 恢复回调
                        LogUtils.i("=== 恢复回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_STOP:
                        // 停止回调
                        LogUtils.i("=== 停止回调  ");
                        break;
                    case SpeechConstants.TTS_EVENT_RELEASE:
                        // 释放资源回调
                        LogUtils.i("=== 释放资源回调  ");

                        break;
                    default:
                        break;
                }

            }

            @Override
            public void onError(int type, String errorMSG) {
                // 语音合成错误回调
                LogUtils.i("=== Error :" + "TTS onError __ type : " + type + " errorMsg : " + errorMSG);
                //TODO 回调 这是干嘛用的？？

                try {

                    if (speechCallbackList != null && speechCallbackList.size() > 0) {
                        LogUtils.d("=== speechError------>onCompleted---" + speechCallbackList.size());
                        for (Request_CallBack request_callBack : speechCallbackList) {
                            request_callBack.setBroadcastResult(BaseConfigs.BROADCASTRESULT.FAILED);
                            long endPlayTime = System.currentTimeMillis();
                            request_callBack.setBroadcastTime((endPlayTime - request_callBack.getBeginPlayTimeLong()) + "");
                            request_callBack.setEndPlayTime(endPlayTime + "");
                            request_callBack.setReason("语音库异常" + errorMSG);
                        }
                        Intent intent = new Intent(MyApplication.application, CallBackService.class);
                        intent.putExtra("speechCallbackList", (Serializable) speechCallbackList);
                        MyApplication.application.startService(intent);
                    }
                    if (errorMSG != null && errorMSG.contains("91103")) {   //{"errorCode":-91103,"errorMsg":"离线tts引擎未初始化，请确认执行init并接收init回调！"}
                        try {
                            offlineResource.setOfflineVoiceType();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
        // 初始化合成引擎
        mTTSPlayer.init("");

    }

    /**
     * 停止播放
     *
     * @author JPH
     * @date 2015-4-14 下午7:50:35
     */
    public void stop() {
        mTTSPlayer.stop();
    }

    /**
     * 播放
     *
     * @author JPH
     * @date 2015-4-14 下午7:29:24
     */
    public void play(OrderVoice orderVoice) {
        playImmediately(orderVoice);
    }

    public void play(OrderVoice orderVoice, PLAY_MODE playMode) {
        switch (playMode) {
            case QUEUED: {
                playQueued(orderVoice);
                break;
            }
            case IMMEDIATELY: {
                playImmediately(orderVoice);
                break;
            }
        }
    }

    private void updateSpeech() {
        if (!isSpeaking) {
            if (speechList.size() > 0) {
                String guid = PreferencesUtils.getString(MyApplication.application, BaseConfigs.STRING_GUID);
                boolean combineVoice = PreferencesUtils.getBoolean(MyApplication.application, BaseConfigs.BOOLEAN_COMBINE_ORDER);
                ConnectivityManager manager = (ConnectivityManager) MyApplication.application.getSystemService(Context.CONNECTIVITY_SERVICE);

                NetworkInfo networkInfo = manager.getActiveNetworkInfo();
                String networkType = "";
                if (networkInfo != null && networkInfo.isConnected()) {
                    networkType = networkInfo.getTypeName();
                }

                speechCallbackList = new ArrayList<>();
                StringBuilder sb = new StringBuilder();
                if (combineVoice) {
                    removeSpeechList = new ArrayList<>();
                    //这里处理合并
                    for (OrderVoice orderVoice : speechList) {
                        //
                        if (!TextUtils.isEmpty(orderVoice.getOrderId()) && !"0".equals(orderVoice.getPayStatus())) {
                            //把要移除的记录下来
                            removeSpeechList.add(orderVoice);
                            //记录回调结果
                            Request_CallBack request_callBack = new Request_CallBack();
                            request_callBack.setOrderId(orderVoice.getOrderId());
                            request_callBack.setGuid(guid);
                            request_callBack.setNetworkType(networkType);
                            request_callBack.setFirstChannel(orderVoice.getFirstChannel());
                            request_callBack.setAchievedTime(orderVoice.getReceiveTime() + "");
                            long beginPlayTimeLong = System.currentTimeMillis();
                            request_callBack.setBeginPlayTime(beginPlayTimeLong + "");
                            request_callBack.setBeginPlayTimeLong(beginPlayTimeLong);
                            speechCallbackList.add(request_callBack);
                            //创建播报内容
                            sb.append("," + orderVoice.getChineseChars());
                        }
                    }
                }
                if (combineVoice && removeSpeechList.size() > 0) {
                    //播报合并的收款单
                    speak(Constants.BRAND_VOICE + "收款" + sb);
                    //不管成功失败都移除合并播放单
                    speechList.removeAll(removeSpeechList);
                } else {

                    //不合并,递归第0个
                    OrderVoice orderVoice = speechList.remove(0);
                    if (orderVoice != null && !TextUtils.isEmpty(orderVoice.getOrderId())) {
                        Request_CallBack request_callBack = new Request_CallBack();
                        request_callBack.setOrderId(orderVoice.getOrderId());
                        request_callBack.setGuid(guid);
                        request_callBack.setNetworkType(networkType);
                        request_callBack.setFirstChannel(orderVoice.getFirstChannel());
                        request_callBack.setAchievedTime(orderVoice.getReceiveTime() + "");
                        long beginPlayTimeLong = System.currentTimeMillis();
                        request_callBack.setBeginPlayTime(beginPlayTimeLong + "");
                        request_callBack.setBeginPlayTimeLong(beginPlayTimeLong);
                        speechCallbackList.add(request_callBack);
                    }
                    boolean cancelAmount = PreferencesUtils.getBoolean(MyApplication.application, BaseConfigs.BOOLEAN_ORDER_CANCEL_AMOUNT);
                    if ("0".equals(orderVoice.getPayStatus()) && cancelAmount) {
                        speak(orderVoice.getContent() + orderVoice.getChineseChars());  // 取零个
                    } else {
                        speak(orderVoice.getContent());
                    }


                }
            }
        }
    }

    private int speak(String content) {
        int voiceSpeed = PreferencesUtils.getInt(MyApplication.application, BaseConfigs.INT_VOICE_SPEED, 0);
        switch (voiceSpeed) {
            case 0:
                mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_SPEED, 51);//语速
                break;
            case 1:
                mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_SPEED, 80);//语速
                break;
            case 2:
                mTTSPlayer.setOption(SpeechConstants.TTS_KEY_VOICE_SPEED, 100);//语速
                break;
        }


        return mTTSPlayer.playText(content);
    }

    public void playQueued(OrderVoice orderVoice) {
        speechList.add(orderVoice);
        updateSpeech();
    }

    public void playImmediately(OrderVoice orderVoice) {
        speak(orderVoice.getContent());
    }

    /**
     * 释放资源
     *
     * @author JPH
     * @date 2015-4-14 下午7:27:56
     */
    public void release() {
        // 主动释放离线引擎
        if (released) {
            return;
        }
        if (mTTSPlayer != null) {
            mTTSPlayer.stop();
            mTTSPlayer.release(SpeechConstants.TTS_RELEASE_ENGINE, null);
        }
        instance = null;
        released = true;
    }


    public enum PLAY_MODE {
        QUEUED,
        IMMEDIATELY
    }


}
